import 'package:easy_debounce/easy_throttle.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:lib_uikit/generated/l10n.dart';
import 'package:lib_uikit/theme/gt_colors_v3.dart';
import 'package:lib_uikit/utils/gt_rtl_property.dart';
import 'package:lib_uikit/utils/gt_screen.dart';
import 'package:lib_uikit/utils/gt_text_style.dart';
import 'package:lib_uikit/utils/text_utils.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';

///新手引导弹窗
class GTGuideUtilV3 {
  /// 展示多功能引导
  static showGuides(List<GTGuideConfig> guides, {VoidCallback? onDismiss}) {
    if (guides.isEmpty) return;
    if (guides.length == 1) {
      _showSingleGuide(guides[0], onDismiss: onDismiss);
      return;
    } else {
      _showGuidesRecursion(guides, guides.length, onDismiss: onDismiss);
    }
  }

  // 递归调用多引导
  static _showGuidesRecursion(List<GTGuideConfig> guides, int maxLength, {VoidCallback? onDismiss}) {
    if (guides.length == 1) {
      _showSingleGuide(guides[0], currentIndex: maxLength - 1, maxLength: maxLength, onDismiss: onDismiss);
      return;
    } else {
      GTGuideConfig gtGuideConfig = guides.removeAt(0);
      bool onNextBefore = false;
      _showSingleGuide(gtGuideConfig, currentIndex: maxLength - guides.length - 1, maxLength: maxLength, onDismiss: () {
        if (onNextBefore) return;
        onDismiss?.call();
      }, onNext: () async {
        onNextBefore = true;
        await SmartDialog.dismiss();
        _showGuidesRecursion(guides, maxLength, onDismiss: onDismiss);
        onNextBefore = false;
      });
    }
  }

  static _showSingleGuide(
    GTGuideConfig gtGuideConfig, {
    int currentIndex = 0,
    int maxLength = 1,
    // 跳过和下一步和知道了按钮的点击回调
    VoidCallback? onSkip,
    VoidCallback? onNext,
    VoidCallback? onGetIt,
    VoidCallback? onDismiss,
  }) {
    BuildContext? context = gtGuideConfig.key.currentContext;
    if (null == context) {
      SmartDialog.dismiss();
      return;
    }

    // 计算目标组件的大小和位置
    RenderObject? renderObject = context.findRenderObject();
    if (null == renderObject) {
      SmartDialog.dismiss();
      return Positioned(left: 0, top: 0, child: Container());
    }
    RenderBox targetRenderBox = renderObject as RenderBox;
    // 目标组件左上角坐标
    Offset targetTopLeftOffset = targetRenderBox.localToGlobal(Offset.zero);
    // 目标组件高亮区域总大小
    double highlightLeft = targetTopLeftOffset.dx - gtGuideConfig.highlightPadding.left;
    double highlightTop = targetTopLeftOffset.dy - gtGuideConfig.highlightPadding.top;
    double highlightHeight = targetRenderBox.size.height + gtGuideConfig.highlightPadding.vertical;
    double highlightWidth = targetRenderBox.size.width + gtGuideConfig.highlightPadding.horizontal;

    SmartDialog.config.attach = SmartConfigAttach(attachAlignmentType: SmartAttachAlignmentType.inside);
    SmartDialog.showAttach(
      targetContext: context,
      onDismiss: () {
        gtGuideConfig.onDismiss?.call();
        onDismiss?.call();
      },
      targetBuilder: (Offset targetOffset, Size targetSize) {
        switch (gtGuideConfig.guideAlignmentType) {
          case GTGuideAlignmentType.topLeft:
            return Offset(highlightLeft, highlightTop) + (gtGuideConfig.popOffset ?? Offset.zero);
          case GTGuideAlignmentType.topCenter:
            return Offset(targetTopLeftOffset.dx, highlightTop) + (gtGuideConfig.popOffset ?? Offset.zero);
          case GTGuideAlignmentType.topRight:
            return Offset(targetTopLeftOffset.dx + gtGuideConfig.highlightPadding.right, highlightTop) +
                (gtGuideConfig.popOffset ?? Offset.zero);
          case GTGuideAlignmentType.centerLeft:
            return Offset(highlightLeft, targetTopLeftOffset.dy) + (gtGuideConfig.popOffset ?? Offset.zero);
          case GTGuideAlignmentType.centerRight:
            return Offset(targetTopLeftOffset.dx + gtGuideConfig.highlightPadding.right, targetTopLeftOffset.dy) +
                (gtGuideConfig.popOffset ?? Offset.zero);
          case GTGuideAlignmentType.bottomLeft:
            return Offset(highlightLeft, targetTopLeftOffset.dy + gtGuideConfig.highlightPadding.bottom) +
                (gtGuideConfig.popOffset ?? Offset.zero);
          case GTGuideAlignmentType.bottomCenter:
            return Offset(targetTopLeftOffset.dx, targetTopLeftOffset.dy + gtGuideConfig.highlightPadding.bottom) +
                (gtGuideConfig.popOffset ?? Offset.zero);
          case GTGuideAlignmentType.bottomRight:
            return Offset(targetTopLeftOffset.dx + gtGuideConfig.highlightPadding.right,
                    targetTopLeftOffset.dy + gtGuideConfig.highlightPadding.bottom) +
                (gtGuideConfig.popOffset ?? Offset.zero);
          default:
            return Offset(highlightLeft, highlightTop) + (gtGuideConfig.popOffset ?? Offset.zero);
        }
      },
      alignment: GTGuideAlignmentType.getAlignment(gtGuideConfig.guideAlignmentType),
      highlightBuilder: (_, __) {
        return Positioned(
          left: highlightLeft,
          top: highlightTop,
          child: Container(
            height: highlightHeight,
            width: highlightWidth,
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(gtGuideConfig.highlightRadius),
              color: GTColorsV3.card2.light,
            ),
          ),
        );
      },
      animationType: SmartAnimationType.fade,
      clickMaskDismiss: false,
      keepSingle: true,
      builder: (_) {
        return _arrowAndPopWidget(
          gtGuideConfig,
          highlightWidth: highlightWidth,
          currentIndex: currentIndex,
          maxLength: maxLength,
          onSkip: onSkip,
          onNext: onNext,
          onGetIt: onGetIt,
        );
      },
    );
  }

  // 箭头和弹框摆放
  static Widget _arrowAndPopWidget(
    GTGuideConfig gtGuideConfig, {
    required double highlightWidth,
    int currentIndex = 0,
    int maxLength = 1,
    // 跳过和下一步和知道了按钮的点击回调
    VoidCallback? onSkip,
    VoidCallback? onNext,
    VoidCallback? onGetIt,
  }) {
    const double arrowPadding = 4;
    switch (gtGuideConfig.guideAlignmentType) {
      case GTGuideAlignmentType.topLeft:
        return Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _popWidget(gtGuideConfig,
                currentIndex: currentIndex, maxLength: maxLength, onSkip: onSkip, onNext: onNext, onGetIt: onGetIt),
            Padding(
              padding: GTEdgeInsetsOnly(
                  left: (highlightWidth / 2) - (12 / 2) + (gtGuideConfig.popArrowTipOffset?.dx ?? 0),
                  bottom: (-(gtGuideConfig.popArrowTipOffset?.dy ?? 0)) + arrowPadding),
              child: _popArrowTipWidget(GTGuidePopArrowTipDirection.bottom, width: 12, height: 8),
            )
          ],
        );
      case GTGuideAlignmentType.topCenter:
        return Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            _popWidget(gtGuideConfig,
                currentIndex: currentIndex, maxLength: maxLength, onSkip: onSkip, onNext: onNext, onGetIt: onGetIt),
            Padding(
              padding: GTEdgeInsetsOnly(
                  left: (gtGuideConfig.popArrowTipOffset?.dx ?? 0),
                  bottom: (-(gtGuideConfig.popArrowTipOffset?.dy ?? 0)) + arrowPadding),
              child: _popArrowTipWidget(GTGuidePopArrowTipDirection.bottom, width: 12, height: 8),
            )
          ],
        );
      case GTGuideAlignmentType.topRight:
        return Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            _popWidget(gtGuideConfig,
                currentIndex: currentIndex, maxLength: maxLength, onSkip: onSkip, onNext: onNext, onGetIt: onGetIt),
            Padding(
              padding: GTEdgeInsetsOnly(
                  right: (highlightWidth / 2) - (12 / 2) - (gtGuideConfig.popArrowTipOffset?.dx ?? 0),
                  bottom: (-(gtGuideConfig.popArrowTipOffset?.dy ?? 0)) + arrowPadding),
              child: _popArrowTipWidget(GTGuidePopArrowTipDirection.bottom, width: 12, height: 8),
            )
          ],
        );
      case GTGuideAlignmentType.centerLeft:
        return Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            _popWidget(gtGuideConfig,
                currentIndex: currentIndex, maxLength: maxLength, onSkip: onSkip, onNext: onNext, onGetIt: onGetIt),
            Padding(
              padding: GTEdgeInsetsOnly(
                  right: (-(gtGuideConfig.popArrowTipOffset?.dx ?? 0)) + arrowPadding,
                  bottom: (-(gtGuideConfig.popArrowTipOffset?.dy ?? 0))),
              child: _popArrowTipWidget(GTGuidePopArrowTipDirection.right, width: 8, height: 12),
            )
          ],
        );
      case GTGuideAlignmentType.centerRight:
        return Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            Padding(
              padding: GTEdgeInsetsOnly(
                  left: (gtGuideConfig.popArrowTipOffset?.dx ?? 0) + arrowPadding,
                  bottom: (-(gtGuideConfig.popArrowTipOffset?.dy ?? 0))),
              child: _popArrowTipWidget(GTGuidePopArrowTipDirection.left, width: 8, height: 12),
            ),
            _popWidget(gtGuideConfig,
                currentIndex: currentIndex, maxLength: maxLength, onSkip: onSkip, onNext: onNext, onGetIt: onGetIt),
          ],
        );

      case GTGuideAlignmentType.bottomLeft:
        return Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Padding(
              padding: GTEdgeInsetsOnly(
                  left: (highlightWidth / 2) - (12 / 2) + (gtGuideConfig.popArrowTipOffset?.dx ?? 0),
                  top: (gtGuideConfig.popArrowTipOffset?.dy ?? 0) + arrowPadding),
              child: _popArrowTipWidget(GTGuidePopArrowTipDirection.top, width: 12, height: 8),
            ),
            _popWidget(gtGuideConfig,
                currentIndex: currentIndex, maxLength: maxLength, onSkip: onSkip, onNext: onNext, onGetIt: onGetIt),
          ],
        );
      case GTGuideAlignmentType.bottomCenter:
        return Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Padding(
              padding: GTEdgeInsetsOnly(
                  left: (gtGuideConfig.popArrowTipOffset?.dx ?? 0),
                  top: (gtGuideConfig.popArrowTipOffset?.dy ?? 0) + arrowPadding),
              child: _popArrowTipWidget(GTGuidePopArrowTipDirection.top, width: 12, height: 8),
            ),
            _popWidget(gtGuideConfig,
                currentIndex: currentIndex, maxLength: maxLength, onSkip: onSkip, onNext: onNext, onGetIt: onGetIt),
          ],
        );
      case GTGuideAlignmentType.bottomRight:
        return Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            Padding(
              padding: GTEdgeInsetsOnly(
                  right: (highlightWidth / 2) - (12 / 2) - (gtGuideConfig.popArrowTipOffset?.dx ?? 0),
                  top: (gtGuideConfig.popArrowTipOffset?.dy ?? 0) + arrowPadding),
              child: _popArrowTipWidget(GTGuidePopArrowTipDirection.top, width: 12, height: 8),
            ),
            _popWidget(gtGuideConfig,
                currentIndex: currentIndex, maxLength: maxLength, onSkip: onSkip, onNext: onNext, onGetIt: onGetIt),
          ],
        );
      default:
        return Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Padding(
              padding: GTEdgeInsetsOnly(
                  left: (highlightWidth / 2) - (12 / 2) + (gtGuideConfig.popArrowTipOffset?.dx ?? 0),
                  top: (gtGuideConfig.popArrowTipOffset?.dy ?? 0) + arrowPadding),
              child: _popArrowTipWidget(GTGuidePopArrowTipDirection.bottom, width: 12, height: 8),
            ),
            _popWidget(gtGuideConfig,
                currentIndex: currentIndex, maxLength: maxLength, onSkip: onSkip, onNext: onNext, onGetIt: onGetIt),
          ],
        );
    }
  }

  // 气泡小尖角
  static Widget _popArrowTipWidget(GTGuidePopArrowTipDirection directionType, {double width = 12, double height = 8}) {
    return CustomPaint(
      painter: TrianglePainter(GTColorsV3.card2.light, directionType),
      child: SizedBox(
        width: width,
        height: height,
      ),
    );
  }

  static Widget _buttonWidget(Color backgroundColor, Color textColor, String text) {
    return Container(
        height: 24,
        padding: const EdgeInsets.symmetric(horizontal: 12),
        alignment: Alignment.center,
        decoration: BoxDecoration(
          color: backgroundColor,
          borderRadius: BorderRadius.circular(20),
        ),
        child: Text(
          text,
          style: gtTextStyleW500(fontSize: 12, color: textColor),
        ));
  }

  // 弹窗
  static Widget _popWidget(
    GTGuideConfig gtGuideConfig, {
    int currentIndex = 0,
    int maxLength = 1,
    // 跳过和下一步和知道了按钮的点击回调
    VoidCallback? onSkip,
    VoidCallback? onNext,
    VoidCallback? onGetIt,
  }) {
    String? title = _breakStrForSpace(gtGuideConfig.title);
    String? content = _breakStrForSpace(gtGuideConfig.content);
    bool isLastGuide = currentIndex == maxLength - 1;
    return Container(
      width: gtGuideConfig.popWidth ?? (GTScreen.width * (3 / 5)),
      decoration: BoxDecoration(
        //弹窗圆角
        borderRadius: BorderRadius.circular(6),
        color: GTColorsV3.card2.light,
      ),
      padding: const EdgeInsets.all(12),
      child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
        if (TextUtils.isNotEmpty(title))
          Text(
            title!,
            style: gtTextStyleW700(color: GTColorsV3.text1.light, fontSize: 14),
          ),
        if (TextUtils.isNotEmpty(title) && TextUtils.isNotEmpty(content)) const SizedBox(height: 8),
        if (TextUtils.isNotEmpty(content))
          Text(
            content!,
            style: gtTextStyleW400(color: GTColorsV3.text2.light, fontSize: 12),
          ),
        const SizedBox(height: 12),
        Row(
          children: [
            if (gtGuideConfig.showIndexIndicator && maxLength > 1)
              Row(mainAxisSize: MainAxisSize.min, children: [
                Text('${currentIndex + 1}', style: gtTextStyleW500(color: GTColorsV3.text1.light, fontSize: 12)),
                Text('/$maxLength', style: gtTextStyleW500(color: GTColorsV3.text3.light, fontSize: 10)),
              ]),
            const Spacer(),
            if (!isLastGuide && gtGuideConfig.showSkip)
              Padding(
                padding: GTEdgeInsetsOnly(left: 12),
                child: GestureDetector(
                  onTap: () {
                    if(gtGuideConfig.handleOnSkip??true){
                      SmartDialog.dismiss();
                      onSkip?.call();
                    }
                    gtGuideConfig.onSkip?.call();
                  },
                  child: _buttonWidget(
                      GTColorsV3.neutral1.light, GTColorsV3.text1.light, LibUIKitS.current.uikit_guide_skip),
                ),
              ),
            if (!isLastGuide && gtGuideConfig.showNext)
              Padding(
                padding: GTEdgeInsetsOnly(left: 8),
                child: GestureDetector(
                  onTap: () {
                    EasyThrottle.throttle("uikitGuideClick", const Duration(milliseconds: 500), () async {
                      if (gtGuideConfig.onNext != null) {
                        await gtGuideConfig.onNext!();
                      }
                      onNext?.call();
                    });
                  },
                  child: _buttonWidget(
                      GTColorsV3.brand1.light, GTColorsV3.text6.light, LibUIKitS.current.uikit_guide_next),
                ),
              ),
            if (isLastGuide)
              Padding(
                padding: GTEdgeInsetsOnly(left: 12),
                child: GestureDetector(
                  onTap: () {
                    SmartDialog.dismiss();
                    onGetIt?.call();
                    gtGuideConfig.onGetIt?.call();
                  },
                  child: _buttonWidget(
                      GTColorsV3.brand1.light, GTColorsV3.text6.light, LibUIKitS.current.uikit_guide_finish),
                ),
              ),
          ],
        )
      ]),
    );
  }

  // 打断空格
  static String? _breakStrForSpace(String? str) {
    if (TextUtils.isEmpty(str)) return str;
    String breakedStr = '';
    str!.split(' ').forEach((element) {
      breakedStr += element;
      breakedStr += '\u200B ';
    });
    return breakedStr.trim();
  }
}

class GTGuideConfig {
  final GlobalKey key;
  final String? title;
  final String? content;
  final GTGuideAlignmentType? guideAlignmentType;

  // 弹框宽度和偏移
  final double? popWidth;
  final Offset? popOffset;

  // 弹框箭头的偏移
  final Offset? popArrowTipOffset;

  // 是否展示下标指示器
  final bool showIndexIndicator;

  // 是否展示跳过
  final bool showSkip;

  // 是否展示下一步
  final bool showNext;

  // 高亮区域圆角
  final double highlightRadius;

  // 高亮区域边距（可以为负值）
  final EdgeInsets highlightPadding;

  // 跳过和下一步和知道了按钮的点击回调
  final VoidCallback? onSkip;
  final VoidFutureCallBack? onNext;
  final VoidCallback? onGetIt;
  final VoidCallback? onDismiss;

  //是否直接执行onSkip，默认直接执行
  final bool? handleOnSkip;

  GTGuideConfig(
      {required this.key,
      this.title,
      this.content,
      this.popWidth,
      this.popOffset,
      this.popArrowTipOffset,
      this.guideAlignmentType,
      this.showIndexIndicator = true,
      this.showSkip = true,
      this.showNext = true,
      this.highlightRadius = 4,
      this.highlightPadding = EdgeInsets.zero,
      this.onSkip,
      this.onNext,
      this.onGetIt,
      this.onDismiss,
      this.handleOnSkip});
}

/// 气泡尖角方向
enum GTGuidePopArrowTipDirection { top, bottom, right, left }

/// 气泡对齐方式
enum GTGuideAlignmentType {
  topLeft,
  topCenter,
  topRight,
  centerLeft,
  centerRight,
  bottomLeft,
  bottomCenter,
  bottomRight;

  static Alignment getAlignment(GTGuideAlignmentType? guideAlignmentType) {
    if (null == guideAlignmentType) return Alignment.bottomCenter;
    switch (guideAlignmentType) {
      case GTGuideAlignmentType.topLeft:
        return Alignment.topLeft;
      case GTGuideAlignmentType.topCenter:
        return Alignment.topCenter;
      case GTGuideAlignmentType.topRight:
        return Alignment.topRight;
      case GTGuideAlignmentType.centerLeft:
        return Alignment.centerLeft;
      case GTGuideAlignmentType.centerRight:
        return Alignment.centerRight;
      case GTGuideAlignmentType.bottomLeft:
        return Alignment.bottomLeft;
      case GTGuideAlignmentType.bottomCenter:
        return Alignment.bottomCenter;
      case GTGuideAlignmentType.bottomRight:
        return Alignment.bottomRight;
      default:
        return Alignment.bottomCenter;
    }
  }
}

/// 气泡尖角组件
class TrianglePainter extends CustomPainter {
  // 尖角颜色
  final Color color;
  final GTGuidePopArrowTipDirection directionType;

  TrianglePainter(this.color, this.directionType);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = color
      ..style = PaintingStyle.fill; // Change this to PaintingStyle.stroke if you want only the outline of the triangle
    final path = Path();
    const double cornerRadius = 1.0; // 设置圆角的大小为1像素
    switch (directionType) {
      case GTGuidePopArrowTipDirection.top:
        path.moveTo(size.width / 2, 0);
        path.lineTo(size.width, size.height);
        path.lineTo(0, size.height);
        break;
      case GTGuidePopArrowTipDirection.bottom:
        path.moveTo(size.width / 2, size.height);
        path.lineTo(size.width, 0);
        path.lineTo(0, 0);
        break;
      case GTGuidePopArrowTipDirection.right:
        path.moveTo(size.width, size.height / 2);
        path.lineTo(0, size.height);
        path.lineTo(0, 0);
        break;
      case GTGuidePopArrowTipDirection.left:
        path.moveTo(0, size.height / 2);
        path.lineTo(size.width, size.height);
        path.lineTo(size.width, 0);
    }
    path.close();
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}
